﻿/*------------------------------------------------------------------------

LIGHTATTRIBRD.HPP v1.1.5

Copyright 楊志賢 CxxlMan, 2014
All Rights Reserved

燈光屬性相關的控制

------------------------------------------------------------------------*/

#if !defined(__LIGHTATTRIBRD_HPP_Cxxl3D)
#define __LIGHTATTRIBRD_HPP_Cxxl3D

#include <Sys\RenderUnit\SYSDDCLASSID.HPP>
#include <Sys\RENDERUNIT.HPP>

namespace Cxxl3D
{

// Render 單元要叫用 ILightAttribRD 提供給其叫用的功能，須繼承此介面
class ILightAttribBridge;


// Render 單元須實作的的介面
class ILightAttrib_CEO
{
public:
  ILightAttrib_CEO(){}
  virtual ~ILightAttrib_CEO(){}

  // 燈光功能 true = ON  false = OFF 
  virtual void cxxlFASTCALL Light(bool Switch) = 0; 

  // 反光功能 true = ON  false = OFF 
  virtual void cxxlFASTCALL Specular(bool Switch) = 0;

  // Switch = true:計算每個頂點到鏡頭的向量 false:假設頂點就在鏡頭前方，加快速度
  virtual void cxxlFASTCALL Specular_LocalViewer(bool Switch) = 0;

  // 設定顏色
  virtual void cxxlFASTCALL SetColor(C3D_FLOAT *Color) = 0;

  // 設定 Emissive 顏色
  virtual void cxxlFASTCALL SetEmissive(C3D_FLOAT *EmissiveColor) = 0;

  // 設定材質反光銳利度
  virtual void cxxlFASTCALL SetMaterialShininess(C3D_FLOAT MaterialShininess) = 0;

  // 是否為 Normalize 做正規化處理
  // Switch = true:是  false:否
  // virtual void cxxlFASTCALL AutoNormalize(bool Switch) = 0;

};


class ILightAttribRD:public IRenderDatagram
{
  // 這裡須傳回 IRenderDatagram 的 "實作介面"，即被 cxxlCM_GetElement() 叫用的 InterfaceID
  CxxlMan::UNICODE_String cxxlFASTCALL GetRenderDatagramID() const
  {
    return ILightAttrib_ClassID;
  }

  // 傳回 IRenderDatagram 的 "實作介面"
  virtual void *cxxlFASTCALL GetDefaultInterface()
  {
    return this;
  }

  // 比對各屬性，不符就呼叫 ILightAttrib_CEO，由 Render 單元叫用
  virtual void cxxlFASTCALL Chk(const CxxlMan::Smart_Ptr<ILightAttribRD> &IAttribRD_Arg, ILightAttrib_CEO *ILightAttrib_CEO_Arg) = 0;

  // 由 Render 單元叫用，設定所有屬性
  virtual void cxxlFASTCALL SetAll(ILightAttrib_CEO *ILightAttrib_CEO_Arg) = 0;

  // 由 Render 單元叫用，並恢復設定為 false
  virtual bool cxxlFASTCALL isModified() = 0;



protected:
  // 儲存容器藉此取得要永續存取的屬性資料
  // 延伸類別須以 virtual 的形式覆寫
  // 並且須呼叫上層類別的此函數
  virtual bool cxxlFASTCALL Ref(CxxlMan::Filter *F)
  {
    if(F != NULL && IRenderDatagram::Ref(F))
      return true;
    else
      return false;
  }

  // 內部用
  virtual void *cxxlFASTCALL GetImp() = 0;
  void *cxxlFASTCALL GetImp(const CxxlMan::Smart_Ptr<ILightAttribRD> &IAttribRD_Arg)
  {
    return IAttribRD_Arg->GetImp();
  }


  // Constructor
  ILightAttribRD()
    :cxxlObject(CxxlMan::Spirit_Easy),
    CxxlMan::cxxlPreserve2(ILightAttrib_ClassID) // 在建構時指定 ClassID
  {
  }

  // Destructor
  virtual ~ILightAttribRD() = 0
  {
  }

public:
  

  // 是否使用燈光 
  // Switch = 0:無所謂  1:開  -1:關
  virtual void cxxlFASTCALL Light(char Switch) = 0;

  // 是否反光
  // Switch = 0:無所謂  1:開  -1:關
  // MaterialShininess = 材質反光銳利度，數值越高越集中於一點
  // LocalViewer = true:計算每個頂點到鏡頭的向量 false:假設頂點就在鏡頭前方，加快速度
  virtual void cxxlFASTCALL Specular(char Switch, C3D_FLOAT MaterialShininess,bool LocalViewer=false) = 0;

  // 設定顏色
  virtual void cxxlFASTCALL SetColor(C3D_FLOAT R, C3D_FLOAT G, C3D_FLOAT B, C3D_FLOAT A) = 0;

  // 設定自體發光的顏色
  virtual void cxxlFASTCALL SetEmissive(C3D_FLOAT R, C3D_FLOAT G, C3D_FLOAT B, C3D_FLOAT A) = 0;

  // 是否為 Normalize 做正規化處理
  // Switch = true:是  false:否
  // virtual void cxxlFASTCALL AutoNormalize(bool Switch) = 0;

  // 複製一份，內容相同
  virtual CxxlMan::Smart_Ptr<ILightAttribRD> cxxlFASTCALL Clone() = 0;

  // 建立 ILightAttribRD 物件，失敗傳回 NULL
  static CxxlMan::Smart_Ptr<ILightAttribRD> cxxlFASTCALL Create()
  {
    return CxxlMan::Preserve2_Cast<ILightAttribRD>( CxxlMan::cxxlCM_GetElement(ILightAttrib_ClassID, IRenderDatagram_Group) );
  }

  // 從永存資料產生 ILightAttribRD 物件
  // 失敗傳回 NULL
  static CxxlMan::Smart_Ptr<ILightAttribRD> cxxlFASTCALL Create(const CxxlMan::UNICODE_String &BackupName, const CxxlMan::Smart_Ptr<CxxlMan::IcxxlStorage> &IcxxlStorage_Arg)
  {
    CxxlMan::Smart_Ptr<cxxlPreserve2> cxxlPreserve2_Ptr(NULL);
    CxxlMan::REGENERARETURN_TYPE rt = cxxlCM_Regenera(cxxlPreserve2_Ptr, BackupName, IcxxlStorage_Arg, true);

    if(rt == CxxlMan::Regenera_Success)
      return CxxlMan::Smart_Cast<ILightAttribRD>(cxxlPreserve2_Ptr);
    else
      return NULL;
  }


  friend class CxxlMan::IcxxlStorage;          // Preserve2 元件須加上這個
  friend class CxxlMan::Smart_Ptr<ILightAttribRD>;  // Preserve2 元件須加上這個
  friend class ILightAttribBridge;
};

// Render 單元要叫用 ILightAttribRD 提供給其叫用的功能，須繼承此介面
class ILightAttribBridge
{

protected:
  // 比對各屬性，不符就呼叫 ILightAttrib_CEO，由 Render 單元叫用
  void Chk(const CxxlMan::Smart_Ptr<ILightAttribRD> &hostIAttribRD_Arg,
    const CxxlMan::Smart_Ptr<ILightAttribRD> &ILightAttribRD_Arg, ILightAttrib_CEO *ILightAttrib_CEO_Arg)
  {
    hostIAttribRD_Arg->Chk(ILightAttribRD_Arg, ILightAttrib_CEO_Arg);
  }

  // 由 Render 單元叫用，設定所有屬性
  void cxxlFASTCALL SetAll(const CxxlMan::Smart_Ptr<ILightAttribRD> &ILightAttribRD_Arg, ILightAttrib_CEO *ILightAttrib_CEO_Arg)
  {
    ILightAttribRD_Arg->SetAll(ILightAttrib_CEO_Arg);
  }

  // 由 Render 單元叫用，並恢復設定為 false
  bool cxxlFASTCALL isModified(const CxxlMan::Smart_Ptr<ILightAttribRD> &ILightAttribRD_Arg)
  {
    return ILightAttribRD_Arg->isModified();
  }


public:
  ILightAttribBridge(){}
  ~ILightAttribBridge(){}

};


}   /* namespace Cxxl3D */
#endif

